//
//  MBDMoveScaleImageView.swift
//  MasterBoy
//
//  Created by kyson on 2024/1/13.
//

import UIKit

class MoveScaleImageView: UIView {
    let min_offset: CGFloat = 10

    var originImage: UIImage?
    var imageView: UIImageView
    var gestureStartPoint: CGPoint = CGPoint.zero
    var offsetX: CGFloat = 0.0
    var offsetY: CGFloat = 0.0
    var originSpace: CGFloat = 0.0
    var scale: CGFloat = 1.0
    var lensRect: CGRect = CGRect.zero
    
    override init(frame: CGRect) {
        imageView = UIImageView(frame: frame)
        super.init(frame: frame)
        
        addSubview(imageView)
        isUserInteractionEnabled = true
        isMultipleTouchEnabled = true
        scale = 1.0
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    deinit {
        originImage = nil
        imageView = UIImageView()
    }
    
    func setImage(_ image: UIImage) {
        originImage = UIImage(cgImage: image.cgImage!)
        lensRect = imageView.frame
        moveToX(0, toY: 0)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if touches.count == 2 {
            let twoTouches = Array(touches)
            originSpace = spaceToPoint(twoTouches[0].location(in: self), fromPoint: twoTouches[1].location(in: self))
        } else if touches.count == 1 {
            if let touch = touches.first {
                gestureStartPoint = touch.location(in: self)
            }
        }
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if touches.count == 2 {
            let twoTouches = Array(touches)
            let currSpace = spaceToPoint(twoTouches[0].location(in: self), fromPoint: twoTouches[1].location(in: self))
            
            if originSpace == 0 {
                originSpace = currSpace
            }
            
            if fabsf(Float(currSpace - originSpace)) >= Float(min_offset) {
                let s = currSpace / originSpace
                scaleTo(s)
                originSpace = currSpace
            }
        } else if touches.count == 1 {
            if let touch = touches.first {
                let curr_point = touch.location(in: self)
                offsetX = curr_point.x - gestureStartPoint.x
                offsetY = curr_point.y - gestureStartPoint.y
                
                if fabsf(Float(offsetX)) >= Float(min_offset) || fabsf(Float(offsetY)) >= Float(min_offset) {
                    moveToX(offsetX, toY: offsetY)
                    gestureStartPoint.x = curr_point.x
                    gestureStartPoint.y = curr_point.y
                }
            }
        }
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        // Handle touch end if needed
    }
    
    func moveToX(_ x: CGFloat, toY y: CGFloat) {
        let point = CGPoint(x: x, y: y)
        resetLens(point)
        
        if let cgImage = originImage?.cgImage {
//            imageView.image = UIImage(cgImage: cgImage)
            imageView.image = UIImage(cgImage: cgImage.cropping(to: lensRect)!)
            resetMonitor()

        }
        
    }
    
    func resetLens(_ point: CGPoint) {
        var x, y, width, height: CGFloat
        
        width = frame.size.width / scale
        height = frame.size.height / scale
        
        if width > originImage!.size.width {
            width = originImage!.size.width
        }
        
        if height > originImage!.size.height {
            height = originImage!.size.height
        }
        
        x = lensRect.origin.x - point.x / scale
        y = lensRect.origin.y - point.y / scale
        
        x = (x < 0) ? 0 : x
        y = (y < 0) ? 0 : y
        
        x = (x + width > originImage!.size.width) ? originImage!.size.width - width : x
        y = (y + height > originImage!.size.height) ? originImage!.size.height - height : y
        
        lensRect = CGRect(x: x, y: y, width: width, height: height)
    }
    
    func spaceToPoint(_ first: CGPoint, fromPoint two: CGPoint) -> CGFloat {
        let x = first.x - two.x
        let y = first.y - two.y
        return sqrt(x * x + y * y)
    }
    
    func scaleTo(_ x: CGFloat) {
        scale *= x
        scale = (scale < 0.1) ? 0.1 : scale
        scale = (scale > 10) ? 10 : scale
        moveToX(0, toY: 0)
    }
    
    func resetMonitor() {
        let width = lensRect.size.width * scale
        let height = lensRect.size.height * scale
        imageView.frame = CGRect(x: 0, y: 0, width: width, height: height)
        setNeedsDisplay()
    }
}

